﻿using System.Collections.Generic;
using System.Linq;

namespace Model
{
    public class Functions
    {
        private static CrazyWowStatsEntities _crazyWowStatsEntities;

        public Functions(string connectionString)
        {
            _crazyWowStatsEntities = new CrazyWowStatsEntities(connectionString)
                                         {
                                             CommandTimeout = 60
                                         };
        }

        public Dictionary<Enums.Class, int> GetClassDistribution()
        {
            var characters = _crazyWowStatsEntities.Characters;
            var warrior = characters.Count(f => f.Class == (int?) Enums.Class.Warrior);
            var paladin = characters.Count(f => f.Class == (int?) Enums.Class.Paladin);
            var hunter = characters.Count(f => f.Class == (int?) Enums.Class.Hunter);
            var rogue = characters.Count(f => f.Class == (int?) Enums.Class.Rogue);
            var priest = characters.Count(f => f.Class == (int?) Enums.Class.Priest);
            var deathKnight = characters.Count(f => f.Class == (int?) Enums.Class.DeathKnight);
            var shaman = characters.Count(f => f.Class == (int?) Enums.Class.Shaman);
            var mage = characters.Count(f => f.Class == (int?) Enums.Class.Mage);
            var warlock = characters.Count(f => f.Class == (int?) Enums.Class.Warlock);
            var druid = characters.Count(f => f.Class == (int?) Enums.Class.Druid);

            var classDistribution = new Dictionary<Enums.Class, int>
                                        {
                                            {Enums.Class.Warrior, warrior},
                                            {Enums.Class.Paladin, paladin},
                                            {Enums.Class.Hunter, hunter},
                                            {Enums.Class.Rogue, rogue},
                                            {Enums.Class.Priest, priest},
                                            {Enums.Class.DeathKnight, deathKnight},
                                            {Enums.Class.Shaman, shaman},
                                            {Enums.Class.Mage, mage},
                                            {Enums.Class.Warlock, warlock},
                                            {Enums.Class.Druid, druid}
                                        };

            return classDistribution;
        }

        public Dictionary<string, int> GetGenderDistribution()
        {
            var characters = _crazyWowStatsEntities.Characters;
            var female = characters.Count(f => f.Gender == Enums.Genders.Female);
            var male = characters.Count(f => f.Gender == Enums.Genders.Male);

            var genderDistribution = new Dictionary<string, int>
                                         {
                                             {Constants.Gender.Female, female},
                                             {Constants.Gender.Male, male}
                                         };

            return genderDistribution;
        }

        public Dictionary<Enums.Race, int> GetRaceDistribution()
        {
            var characters = _crazyWowStatsEntities.Characters;
            var human = characters.Count(f => f.Race == (int?) Enums.Race.Human);
            var orc = characters.Count(f => f.Race == (int?) Enums.Race.Orc);
            var dwarf = characters.Count(f => f.Race == (int?) Enums.Race.Dwarf);
            var nightElf = characters.Count(f => f.Race == (int?) Enums.Race.NightElf);
            var undead = characters.Count(f => f.Race == (int?) Enums.Race.Undead);
            var tauren = characters.Count(f => f.Race == (int?) Enums.Race.Tauren);
            var gnome = characters.Count(f => f.Race == (int?) Enums.Race.Gnome);
            var troll = characters.Count(f => f.Race == (int?) Enums.Race.Troll);
            var goblin = characters.Count(f => f.Race == (int?) Enums.Race.Goblin);
            var bloodElf = characters.Count(f => f.Race == (int?) Enums.Race.BloodElf);
            var draenei = characters.Count(f => f.Race == (int?) Enums.Race.Draenei);
            var worgen = characters.Count(f => f.Race == (int?) Enums.Race.Worgen);

            var raceDistribution = new Dictionary<Enums.Race, int>
                                       {
                                           {Enums.Race.Human, human},
                                           {Enums.Race.Orc, orc},
                                           {Enums.Race.Dwarf, dwarf},
                                           {Enums.Race.NightElf, nightElf},
                                           {Enums.Race.Undead, undead},
                                           {Enums.Race.Tauren, tauren},
                                           {Enums.Race.Gnome, gnome},
                                           {Enums.Race.Troll, troll},
                                           {Enums.Race.Goblin, goblin},
                                           {Enums.Race.BloodElf, bloodElf},
                                           {Enums.Race.Draenei, draenei},
                                           {Enums.Race.Worgen, worgen}
                                       };

            return raceDistribution;
        }

        public Dictionary<string, long> GetGeneralStatistics()
        {
            var characters = _crazyWowStatsEntities.Characters.Where(f => f.Level != null);
            var totalCharacters = characters.Count();
            var totalLevels = characters.Sum(f => (int) f.Level);
            var averageLevel = totalLevels/totalCharacters;
            var charactersAtMaxLevel = characters.Count(f => f.Level == 85);
            var maxAchievementPoints = characters.Max(f => (int) f.AchievementPoints);
            var totalAchievementPoints = characters.Sum(f => (long) f.AchievementPoints);
            var averageAchievementPoints = totalAchievementPoints/totalCharacters;
            var maxHonorableKills = characters.Max(f => (int) f.TotalHonorableKills);
            var totalHonorableKills = characters.Sum(f => (long) f.TotalHonorableKills);
            var averageHonorableKills = totalHonorableKills/totalCharacters;
            var generalStatistics = new Dictionary<string, long>
                                        {
                                            {Constants.GeneralStatistics.TotalCharacters, totalCharacters},
                                            {Constants.GeneralStatistics.AverageLevel, averageLevel},
                                            {Constants.GeneralStatistics.CharactersAtMaxLevel, charactersAtMaxLevel},
                                            {Constants.GeneralStatistics.MaxAchievementPoints, maxAchievementPoints},
                                            {Constants.GeneralStatistics.AverageAchievementPoints, averageAchievementPoints},
                                            {Constants.GeneralStatistics.MaxHonorableKills, maxHonorableKills},
                                            {Constants.GeneralStatistics.TotalHonorableKills, totalHonorableKills},
                                            {Constants.GeneralStatistics.AverageHonorableKills, averageHonorableKills}
                                        };
            return generalStatistics;
        }

        public List<ReputationResult> GetReputationStatistics()
        {
            return (from faction in _crazyWowStatsEntities.Factions
                    let currentFaction = _crazyWowStatsEntities.Character_Reputation.Where(f => f.FactionId == faction.FactionId)
                    let hated = currentFaction.Count(f => f.Standing == Enums.Reputation.Hated)
                    let hostile = currentFaction.Count(f => f.Standing == Enums.Reputation.Hostile)
                    let unfriendly = currentFaction.Count(f => f.Standing == Enums.Reputation.Unfriendly)
                    let neutral = currentFaction.Count(f => f.Standing == Enums.Reputation.Neutral)
                    let friendly = currentFaction.Count(f => f.Standing == Enums.Reputation.Friendly)
                    let honored = currentFaction.Count(f => f.Standing == Enums.Reputation.Honored)
                    let revered = currentFaction.Count(f => f.Standing == Enums.Reputation.Revered)
                    let exalted = currentFaction.Count(f => f.Standing == Enums.Reputation.Exalted)
                    select new ReputationResult
                               {
                                   FactionId = faction.FactionId,
                                   ReputationName = faction.Name,
                                   Hated = hated,
                                   Hostile = hostile,
                                   Unfriendly = unfriendly,
                                   Neutral = neutral,
                                   Friendly = friendly,
                                   Honored = honored,
                                   Revered = revered,
                                   Exalted = exalted
                               }).ToList();
        }
    }

    public class ReputationResult
    {
        public int FactionId { get; set; }
        public string ReputationName { get; set; }
        public int Hated { get; set; }
        public int Hostile { get; set; }
        public int Unfriendly { get; set; }
        public int Neutral { get; set; }
        public int Friendly { get; set; }
        public int Honored { get; set; }
        public int Revered { get; set; }
        public int Exalted { get; set; }
    }
}
